﻿using NUnit.Framework;

namespace Visitor
{
    public interface IModem
    {
        void Dial(string pno);
        void Hangup();
        void Send(char c);
        char Recv();
        void Accept(IModemVisitor v);
    }

    public interface IModemVisitor
    {
        void Visit(HayesModem modem);
        void Visit(ZoomModem modem);
        void Visit(ErnieModem modem);
    }

    public class HayesModem : IModem
    {
        public void Dial(string pno) { }
        public void Hangup() { }
        public void Send(char c) { }
        public char Recv() { return (char)0; }
        public void Accept(IModemVisitor v) { v.Visit(this); }

        public string configurationString = null;
    }

    public class ZoomModem : IModem
    {
        public void Dial(string pno) { }
        public void Hangup() { }
        public void Send(char c) { }
        public char Recv() { return (char)0; }
        public void Accept(IModemVisitor v) { v.Visit(this); }

        public int configurationValue = 0;
    }
    
    public class ErnieModem : IModem
    {
        public void Dial(string pno) { }
        public void Hangup() { }
        public void Send(char c) { }
        public char Recv() { return (char)0; }
        public void Accept(IModemVisitor v) { v.Visit(this); }

        public string internalPattern = null;
    }
    
    public class UnixModemConfigurator : IModemVisitor
    {
        public void Visit(HayesModem m)
        {
            m.configurationString = "&s1=4&D=3";
        }

        public void Visit(ZoomModem m)
        {
            m.configurationValue = 42;
        }
        public void Visit(ErnieModem m)
        {
            m.internalPattern = "C is too slow";
        }
    }

    [TestFixture]
    public class ModemVisitorTest
    {
        private UnixModemConfigurator v;
        private HayesModem h;
        private ZoomModem z;
        private ErnieModem e;

        [SetUp]
        public void SetUp()
        {
            v = new UnixModemConfigurator();
            h = new HayesModem();
            z = new ZoomModem();
            e = new ErnieModem();
        }

        [Test]
        public void HayesForUnix()
        {
            h.Accept(v);
            Assert.AreEqual("&s1=4&D=3", h.configurationString);
        }

        [Test]
        public void ZoomForUnix()
        {
            z.Accept(v);
            Assert.AreEqual(42, z.configurationValue);
        }

        [Test]
        public void ErnieForUnix()
        {
            e.Accept(v);
            Assert.AreEqual("C is too slow", e.internalPattern);
        }
    }

}
